Thanks for joining Mac.
In this lecture.
We're going to take a look at how to create a simple crafting system.
Before we get started, though, we'll have to do a little bit of setup.
I've attached this guy to the lecture that you'll need to follow along, and I've also attached some
tool models that I've placed here inside of a folder called Craftable Items.
Just some random tools I made that will be using as an example for our crafting system.
So you'll want to go ahead and grab these before we get started.
Another thing we must do is that I've created a remote function and replicated storage.
I've just called it request craft info, and we're going to be using this to communicate between the
client and server when they need to craft something.
But once we've got all of this finished, then we can go ahead and get started into our scripting.
So inside of server script service, I'm going to create a server script and I'll just name it crafting
System handler.
And this is going to handle all of the crafting and server validation stuff.
So the first thing we need are some services.
We're going to need some variables as well as functions and then some event handlers.
So the services we're going to be needing for our service script is that first we need the player service.
We're also going to need to get access to replicated storage so we can reference that event in there.
And then we'll also need a reference to server storage so we can grab those tools and give them to our
player when they want to craft something.
So let's go ahead and reference that event.
I'll just call it craft event, and it's going to be equal to replicated storage and get a reference
to our request craft info, remote function.
And then I'm also going to reference the folder that houses all of our tools.
So server storage dot craftable items.
The next thing I'm going to do is I'm going to create a table.
I'll just call it craftable items.
And this table is going to store the information of what materials we exactly need for each of the items.
So one of our tools is a wooden pickaxe.
We want to make sure that this key is the exact same as the name of our tool.
And in here, I'm just going to store a table and this table is going to have a key value pair.
One of the materials I'll have is wood and I'll set that equal to five.
So for our wooden pickaxe, we need five wood.
Then we could do for our stone pickaxe.
We'll need.
Let's say we'll need two wood, and then we'll also need three stone.
And then we could do the same for our iron pickaxe.
Again.
We'll need to wood and then we'll need three iron.
And then the last thing, we'll have a crystal pickaxe.
And again, we'll need to wood and then we'll have three crystal.
I'm going to create one more table.
I'm going to call it craft bounce.
And what this table is going to do is it's going to store the names of the players who fire this remote
function.
And I'm going to keep track of them that way.
You know, they can't sit there and spam the remote function a bunch of times.
Now, one function we're going to need is for our remote function.
So I'm going to call this function on craft event.
So whenever this function gets called from the client to the server, it's first going to pass to us
a player, the player who called this remote function from the client.
I guess we'll pass in action what we want the client to do for us and that's going to be a string and
then we'll pass another string and that's going to be the name of the item that the player wants to
craft.
So we'll have that function.
And then we're also going to need another function.
And this function I'll just call it create int value.
And with this function is going to do for us is that when a player joins our game, we're going to create
a folder that's a child of the player and that folder is going to store all of the materials that player
has and it's going to be stored in an int value so that int value will have a name, it'll have a value,
and then we'll set the parent for that int value.
So we'll actually do that real quick in this function we'll just create a new int value.
The int value.
Dot name is going to be equal to the name that is passed to the function.
Same thing for the value.
And then the same thing for the parent.
And that's all we need this function to do.
Before we fill out this function, we should create our event handlers and one is going to be for the
player added event and the player service will connect a function to that and get the player that is
added.
We'll also need to listen to when our remote function gets called.
So craft event.
On server is invoked, it's going to be equal to that on craft event function.
So the on server invoke property is referencing our function and this function is going to execute and
do the functionality we want the server to do.
One more event I think I need to listen to is when a player gets removed from our game.
And the reason we need to do this is because I'm going to be storing player names in here and it's going
to be equal to a Boolean to see whether or not they've already fired this remote event.
But if the player leaves the game, then I need to clear their name out of this table so we don't keep
sucking up names inside of this table and storing memory that we don't need to because let's say the
lifetime of the server is around for a long time and it just keeps storing more and more and more player
names.
It's going to take up memory that can be freed later.
So actually what we could do is we could check if that if the craft debounce table has a key value pair
for this player.
Then what we could do is we could just set it to nil, which allows us to free up the memory.
Now, when a player joins our game, we want to create a new folder for them.
We'll call it material folder.
Older.
The name of our material folder is going to be materials.
And then the material folder parent is going to be equal to that player instance.
Next.
What we could do is we could call that create value function and create all of those materials a player
should have.
So one material is going to be wood, and when they join the game, we'll just give them a default of
zero.
And the parent for that is going to be that material folder we just created.
And then we can actually just copy this and paste this function four more times and then we can do one
for stone.
We can do one.
For iron.
And then we can do one for crystal.
And I think that's all we need to do there.
So when a player joins our game, we create a bunch of new INT values in a folder for the player, and
that folder belongs to that specific player instance.
So whenever the player is in our game, they'll have this on our screen and they'll be able to open
the GUI with these buttons.
So if I actually go to the crafting UI here, one of the frames show us the items we can craft.
And my idea is to tween the position to show on the screen when they press that button and it'll show
us the items that they can craft, and then there'll be another side that will show them what materials
they have.
So it'll show them the materials and it'll show them the quantity of the materials.
And to do that, I actually have some frames in here and this is just going to be an example.
But if I put it into the scrolling frame and then I actually enable the visibility, it'll display the
name of the material and then it'll display the quantity of the material.
Let me just put that back real quick.
And then for our item frame, we have a button actually, because the player will click that button.
If they want to craft it, let's put it in the scrolling flame.
It'll show them the name of the item and it'll also list out the requirements or what exactly materials
they'll need to craft that item.
So let me move these frames back to their default positions.
And we can fill out the rest of our server script.
So what do we want to happen when a player presses one of those buttons and they want to craft an item?
Well, the first thing we need to do is to check if the string that the player passes to the server,
the action is, let's say the action is equal to craft item.
So they want to craft an item, right?
So if they want to craft an item, then the first thing we need to do is we need to check if they have
that debounce.
So if they have a key value pair in the table, right?
And it's true, then we're going to return.
And because this is a remote function, we actually have to return something back.
I'm just going to return false.
As you know, they can't craft the item because they're currently in a debounce and then after that
we can actually.
Set a key value pair for them to true.
That way they can't you know spam this remote function because exploiters could do that.
Once we verify that this is their first calling of this function, we need to create some references
to the folder that is in the player.
So player materials.
We'll get there materials folder that we create when the player first joins the game.
We're also going to create a variable that's going to keep track of whether or not this item that they're
requesting to craft can be crafted or not.
And by default, I'm going to set it to false.
And then we'll also need a table.
I'll call it materials.
Materials to be deducted.
Set it to a table, because what we're going to do is we're going to loop through all of the materials
in the player and see if they have enough of the requirements that are defined up here to be able to
craft the item.
And if they do, then we'll put all those materials they need to deduct in this table and we'll deduct
it from those values that are in their materials folder.
Now, one thing we need to check is whether or not the string this name, they want to craft the item.
Right.
If it exists in our craftable items table.
So what we could do is that if this item the requesting the craft does not exist within our craftable
items table, then we can set their craft bounce back to false.
Or actually, you know what?
We don't need to do that.
We'll just return.
False.
And we actually put this as one of the first things we can check here.
So if the item that they're requesting to craft, if it doesn't exist, then we're going to return.
Once we get this finished, we're going to loop through every single material and the amount that is
required for the specific item they want to craft.
So, for example, if they pass a string of wooden pickaxe, we're going to loop through every single
key value pair in this table.
For this one, it's just one.
So we'll get the material, which is wood, and then the amount is five.
So for every material and amount in pairs, we're going to get the craftable items table and we're going
to get the item name.
So this particular.
Key value pair.
What we're going to do is we'll check if if the players materials folder if it doesn't have.
Fine first child this material.
Or.
We could say oops.
Materials.
Or let's say the player materials folder of this player if they do have this material.
But the amount of materials they have, like let's say they only have one wood and they need five wood
to craft the wooden pickaxe, Obviously we can't craft it, so we'll have to return false.
So if it's less than the amount that is required for this specific item.
Then what we could do is we could.
Set can be crafted actually to false, because what I'm going to do is actually set this to true.
So we're going to assume that the item they want to craft can be crafted until proven otherwise.
So when we loop through every single material and amount they need for this particular item, if they
don't have this material in their player materials folder or they don't have enough quantity of this
material, then we're going to set can be crafted to false and we're going to break out of this loop.
Because at the very end of this if statement, what we'll do is we'll just return can be crafted.
Otherwise what we could do.
If the player has this material in their player's material folder and they actually have enough amount,
right, they have enough quantity to craft the item, then we'll insert it into the materials to be
deducted table.
So we could do materials to be deducted, pass that material and the amount.
So it'll loop through everything.
So if they want to craft a crystal pickaxe, it'll be like, okay, you need to wood.
So it'll check if the player has a wood material in their players folder and if they have enough quantity,
which would be two.
If they do, then we'll put it in the table and then we'll loop to the next one.
So they need three crystal.
If they only have two, then we'll break out of this loop and we'll have this variable be set to false,
and then we'll return.
We'll tell the player, Hey, you know, you can't craft this thing because you don't have enough materials.
So once we're done looping, it can be crafted is still true.
So if can be crafted, that means they passed everything they have, all the materials they need.
Then what we could do is we could loop through every single material and the materials to be deducted
table.
So for every material and its value in pairs, materials to be deducted.
What we're going to do is we're going to reference their materials folder.
Get that material.
And then we're going to set the value of that material minus equal the value we get here.
So we're deducting whatever material quantity they have to craft this item.
Once we do all of that and we deduct all their materials, then we can clone one of those tools.
And we created a reference earlier to the tools folder and then we can actually get the tool name,
which was the item name passed to us, since the names in here match the tool.
And we can just clone this tool.
And once we have this clone, we can set the parent of the clone equal to the player's backpack.
And then before we return can be crafted, we got to make sure to set craft balance for this player
back to false so they're able to craft again.
All right.
Seems pretty good.
One more thing I want to check here is I want to check if the action the is requesting the server to
do is an action like get craftable items.
And the reason I'm doing this is because I don't want to put a bunch of buttons inside of our item frame
that lists the current items we can craft.
Because let's say down the line I add more and more items to craft.
That means I would have to update the GUI each time.
I would have to update the frames in the GUI, and then I'd also have to update this table.
But it would be better if I could just only update this table and not have to worry about updating the
buttons that are going to be in our item frame.
So what that means is that when a player joins the game, they can request to get all of the craftable
items that exist and we can return that table back to them.
And because we're turning that table back to them, they can loop through every single one of those,
create a bunch of these item buttons, set the name and then the requirements.
And that way we don't have to sit there and create a bunch of buttons inside of our scrolling frame.
But whatever.
You'll see what I mean in a moment.
Otherwise our server script is looking pretty good.
The next thing we need to do is to create a local script inside of our crafting GUI so that way we can
listen for when the player clicks all the buttons in their.
So inside of our guy will, of course, need some services.
We're going to need variables.
We're going to need actually some constants.
As well as functions.
Event handlers.
And then we'll actually have a main section where we're going to invoke the server with the request
craft info, remote function, and we're going to get that table I was talking about earlier so we could
set up our GUI.
So the first service we need, of course, is replicated storage to get access to that event.
We're going to need the player service.
That way we can get a reference to our local player.
And then we're actually going to need the tween service.
That way we can tween elements specifically when we click those buttons, we want to tween the UI onto
the screen and then tween it off the screen.
So it's nice and smooth.
Now that we've got that done, we need some variables.
One is going to be for our event.
And we'll wait for the request craft info to be replicated because this local script is going to run
immediately.
We'll need a reference to the local player.
And we'll need a reference to the guy itself, which is apparent.
And then inside of this guy, I want to reference the item frame.
And I also want to reference the material frame.
Um, I'll also want to reference those two examples.
So I made an example item button and the item frame, and then I made an example material frame inside
of the materials frame.
So I want to reference those two so I can clone them later.
So example item button is equal to the item frame and we'll wait for the example item button to replicate.
And then we'll do the same, for example, material frame.
Material frame wafer child.
The example material frame.
Now, what are these constants I need?
Well, one of the constants I'll need is a string, and it's going to be called quantity.
String.
What is this going to be?
It's just going to be a string that says quantity.
Because I'm going to be using the string to concatenate the quantity of the materials a player has.
And I don't want to have to copy and paste the same string in multiple spots that just wastes more memory.
Instead, I can just store it in one constant and then reference that constant so I save on memory.
Another constant I'll need is the position for our item frame when it's visible and when it's not visible.
So we can call this first one item frame hidden and it's going to be equal to a new item to.
So when our item frame is hidden right here on the right side of the screen, it's currently at an X
scale position of one.
So for the first number in here, it's got to be the X scale position.
So that's going to be one.
The offset is zero and then the Y scale is going to be that particular item frame.
So item frame dot position, we get the Y and then we get the scale.
The offset is zero.
Then we can copy this.
And do it for when the frame is visible.
And if you remember, the frame is visible when we are at a scale position on the x axis of 75%.
Keep the same Y scale and then we could just copy these two and do the same for the material frame.
So material frame.
When the material frame is hidden, our X scale is going to actually be at zero.
And when it's visible, our X scale is going to be at 0.25 and then we'll make sure to get the material
frame position on the Y axis.
All right.
That seems pretty good.
Now, some functions we're going to need.
One function is going to be for when we click one of these item buttons.
So we're going to have a list of four pickaxes we can craft.
Now, I don't want to create a lambda function for each one of those buttons because that just wastes
memory.
Instead, I can have each button reference the same function.
So in particular, it's going to be this function.
I'm going to name it on item button clicked.
We're going to pass the button that got clicked to this function.
And what we'll do is we'll have that request craft event.
We're going to invoke the server.
And we're going to tell the server we want to craft an item and that item is going to be the button
dot item name, label, dot text.
So inside of this button I have a text label that's going to represent the name of the tool we can craft.
So one will be wooden pickaxe, one will be crystal Pickaxe and so on.
So we're telling the server, Hey, we want to craft an item.
Which item is it?
It's the text that is in the button.
We clicked.
And then we can actually store the result from this.
And then we can print that results.
In the console.
Next, we'll need a function for listening when those int values that are inside of our materials folder
get updated.
So let's say a value gets deducted or a value gets added to that int value.
I want to be able to update those numbers in our guy so we can call this function on int value updated.
We'll pass that int value to this function itself and then we'll also pass the label that's going to
update the quantity.
So we're going to call it quantity label and that's what we're going to be using this quantity string
for.
So inside of our example material frame, there is a quantity label here and it's going to display the
quantity of items for that particular material.
So what we can do is we can get that quantity label and set the text equal to the quantity string,
and then we concatenate it with the int values new value.
So when the int values value changes, we display that new value inside of our quantity label.
Another function we'll need.
Is for those open and closing buttons for each one of those item frames.
So we can call this function on open close button clicked.
And since this function needs to work for each one of those buttons, what I'll actually do is we'll
pass what frame we need to tween.
And then we'll pass the UDM position we want to tween to, which is why we created these constants.
So we're going to call this function and pass those constants so we can, you know, tween the frame
left and right.
And what we'll do is we'll reference the tween service and we're going to create a new tween.
The tween is going to be on that frame, the tween.
We'll create a new tween info.
And it'll just be like, one second, let's just do that.
And then what do we need to tween We need to tween the position of our UI element, which is going to
be equal to that udim position that gets passed to this function.
And then we just play the tween.
Think that's all we need this function to do.
Now that we've got all that done, I think that's actually all the functions we'll need.
Now we need to handle some events.
What events we need to handle.
Well, the first events we can handle are the open and close buttons for our crafting GUI.
So we could do material frame.
Um, we'll wait for the open button.
And when that button gets clicked, we're going to connect a lambda function to it.
And we're going to call the on open close button clicked past the material frame.
And then we're going to pass material frame visible because this is the open button we want to tween
the material frame to be visible.
Once we do that, what I want to do is in the material frame, I want to set the open button to be no
longer visible because we just opened it.
And then I also want to set the close button to be visible so that way we can close the GUI.
And then we can actually just copy this and do the same thing for the close button.
And instead we want the frame to be hidden.
And we can just reverse these booleans here.
So we want the open button to be visible and we want the close button to not be visible.
And we can just copy these again and do the same thing for the open and close buttons on the item frame.
There is a more efficient way to do this, but this is probably the easiest way.
And then we want to pass the item frame itself to this function.
And we want to reference that here as well.
So change these references.
And then we need to change this to item frame instead of material frame.
Just like that.
All right.
So that's all the event handlers we need to listen to for this section.
Now, what we're going to do is I'm going to create a variable.
I'm going to call it craftable items, and it's going to be equal to the request craft event.
We're going to invoke the server and we're going to get all the current craftable items.
So we're going to get that table that's going to be returned from us from the server, this table right
here.
Once we've grabbed this table, what we could do now is we can loop through it.
So for every single item and its requirements inside of this table, craftable items, what we're going
to do is we're going to create a bunch of buttons for each of the items.
So I'm going to create a clone and this clone is going to be a clone of the example item button.
For this clone.
I'm going to set the item name, label the name of our item.
We need to craft set the text equal to that item.
And then what I'm going to do next is for every single material and the amount required inside of the
requirements table for this particular item.
So for every single material and amount for this particular requirements for the item, we're going
to set the clone.
And get the requirements label and we're going to set the text equal to itself.
So we're actually going to copy this.
We're going to set this text to itself and then we're going to concatenate it with the amount.
Concatenate that amount with a space and then concatenate it with the name of the material and then
concatenate it with a comma.
And a space.
So through the first iteration of the loop, let's say it'll say something like requires three would
and then comma and then it adds on another amount.
So this amount will be maybe.
Uh, two crystal comma, and then it goes through all the amounts and sets the requirements label to
that text.
Once we've got this done for this particular clone, this particular example item button, we need to
listen for when it gets clicked.
So mouse button one click, we're going to connect a lambda function.
And the reason I'm not referencing our on item button clicked is because I actually have to pass the
button itself for this function to work.
So I need to pass the button and in order to do that I have to create a lambda function here.
So inside I can call the on item button clicked and then pass the clone to this function.
Once that's done, we can set the parent of the clone equal to the item frame and we're going to wait
for the scrolling frame just in case it hasn't replicated yet.
And then of course, we need to set the visibility of this button to true.
Now, the next thing we need to do is we are going to have to loop through every single one of those
int values that are a part of our materials folder.
That way we can now set up the materials frame in our guy.
So to do that we're going to get every single int value and I'm going to make sure to denote this as
an int value and I pairs, we're going to get the local player.
We're going to wait for the materials folder in case it hasn't replicated yet and we're going to get
the children inside of this folder.
So for every single one of these int values, we're going to create a clone of the example material
frame.
The material name label for the clone is going to be equal to the int value.name the name of the int
value.
The clone quantity label text, of course, is going to be equal to quantity string and concatenate
it with the int value.
Dot value.
And then we can do something like int value.
We're going to get property change signal.
What property do we want to listen to for when it changes?
Well, we want to listen to when the value changes.
And when the value changes, what do we want to do?
Well, we want to call that on int value updated function.
We want to pass this particular int value to the function as well as the quantity label that is a part
of this particular material frame clone.
So that way this function will update the text in this quantity label to the correct value that is in
this int value.
And that happens every time the value property gets updated or changed.
And again, we need to set the parent of this clone to be equal to the material frame.
And we're going to wait for the scrolling frame in case it hasn't been replicated.
And then we're going to set the visibility of the clone to true as well.
Now, one thing I'm going to do just in case is I'm going to listen for when any children gets added
to our materials folder.
So let's say down the line.
Maybe the player gets a new material later in the game.
Well, I want to make sure to be able to update that in my guy.
So what we could do is we can access the materials folder.
I don't have to wait for it here because I already waited for it up here.
I don't need to wait for it again.
And we're going to listen to the child added event.
And we're going to get that child that gets added to this folder and we're going to check if this child
is not an int value, then we don't care.
We're going to return.
Otherwise, if it isn't in value, then we're going to make another clone of the example material frame.
And technically we can actually just copy the same thing here.
Um, we'll just want to change this to child.
For each one of these references.
And other than that, I think I think we're pretty good for our local script.
So this should be able to handle all of the opening and closing buttons and it should be able to handle
all of the buttons that are going to be inside of our item frame.
And it should also be able to update every single one of the materials inside of the materials frame
for our materials folder so we can actually go ahead and test it out by playing our game.
So when we play our game, we should be able to open and close these menus and there we are.
Perfect.
So as you can see, our loop went through and updated each of the materials and the crafting items that
we can craft, and it's put down the requirements.
So the wooden pickaxe is five wood, crystal, pickaxe, two wood, three crystal, blah, blah, blah.
And it's telling us our current quantity for these materials and that's actually stored in this material
folders that are part of our player.
You can see each one of these int values and their value is at zero.
Now if I were to go and look on the server.
And let's say I just updated these values to like ten for each one of them.
And I go back to the client.
The client's GUI should be updated to show each one of these materials set to ten because the value
got changed and it should have fired that event.
And look, there we are.
Each one of the quantities for our materials got set to ten.
And that means we should be able to craft any of these items here that we want.
So let's go ahead and craft maybe a wooden pickaxe.
There we go.
We get our wooden pickaxe.
And because we had that print statement in our local script, it's telling us, hey, our our request
to craft an item was successful and it also detected us five wood.
We could go ahead and try to craft a crystal pickaxe again, took the wood away and it also took the
crystal away.
And now we have our crystal pickaxe.
We can do it for the iron pickaxe.
There we go.
And then if I try to craft the stone pickaxe, it shouldn't let me because I don't have enough wood.
There we go.
We got false.
And of course, in your game you could set it up too.
However, you'd like the player to get more of these materials and these tools don't actually do anything.
They're just models.
But you could also create these tools to do whatever you want for your game.
So maybe the player is in like a mining game and they've got to go mine for materials to get better
pickaxes or whatever the case may be.
But otherwise, this is a very simple way of how to create a crafting system in Roblox.
Obviously you could go absolutely crazy with crafting systems and make them as complex and crazy as
you'd want, but this lecture should be able to demonstrate to you a basic crafting system that should
get you off of your feet and into more scripting.
So I hope you enjoyed this lecture.